home *** CD-ROM | disk | FTP | other *** search
/ Rover 25 Presentation / Rover25_Presentation_CD.bin / Tool2.cst / 00005_Script_Rotation (time-based) < prev    next >
Text File  |  2000-01-31  |  18KB  |  594 lines

  1. -- DESCRIPTION --
  2.  
  3. on getBehaviorDescription me
  4.   return "¼
  5. TIME-BASED ROTATION BEHAVIOR"&RETURN&RETURN&"¼
  6. Rotates a sprite through a given angle over a given time.  ¼
  7. Positive angles rotate sprites clockwise, negative angles rotate ¼
  8. counterclockwise.  Angles greater than 360░ will result in ¼
  9. more than one complete rotation."&RETURN&RETURN&"¼
  10. PERMITTED MEMBER TYPES:"&RETURN&PermittedMemberTypes (me)&RETURN&RETURN&"¼
  11. PARAMETERS:"&RETURN&"¼
  12. * Initial rotation angle"&RETURN&"¼
  13. * Angle to rotate (negative angles = anticlockwise)"&RETURN&"¼
  14. * Duration of the rotation (1 tick to 5 days"&RETURN&"¼
  15. * Start rotating on beginsprite (TRUE | FALSE)"&RETURN&RETURN&"¼
  16. PUBLIC METHODS:"&RETURN&"¼
  17. => Modify initial angle"&RETURN&"¼
  18. => Modify angle to rotate"&RETURN&"¼
  19. => Modify duration"&RETURN&"¼
  20. => Stop/restart rotation"&RETURN&"¼
  21. => Pause/resume rotation"&RETURN&"¼
  22. => Reverse direction"&RETURN&"¼
  23. => Obtain current angle of sprite"&RETURN&"¼
  24. => Obtain the angle turned per tick"&RETURN&"¼
  25. => Obtain behavior reference"
  26. end getBehaviorDescription
  27.  
  28.  
  29. on getBehaviorTooltip me
  30.   return "¼
  31. Use with Bitmap, Flash, Text,"&RETURN&"¼
  32. and Vector Shape members."&RETURN&RETURN&"¼
  33. Turn a sprite through a given"&RETURN&"¼
  34. angle at a steady pace."&RETURN&"¼
  35. Use Lingo to control rotation."
  36. end getBehaviorTooltip
  37.  
  38.  
  39.  
  40. -- NOTES FOR DEVELOPERS --
  41.  
  42. -- This behavior uses four angle properties:
  43. -- * myInitialAngle: the starting angle for the rotation
  44. -- * myTotalAngle:   how many degrees the sprite is to rotate through
  45. -- * myAnglePerTick: the angle the sprite will turn on each tick
  46. -- * myFinalAngle:   the angle at which the sprite will stop rotating
  47. --
  48. -- I calculate myFinalAngle in the StartRotation handler by adding
  49. -- myTotalAngle to myInitialAngle.  I divide myTotalAngle by the duration
  50. -- to obtain myAnglePerTick.
  51. --
  52. -- I use five properties to deal with the time:
  53. -- * myDuration:   the total number of ticks during which the sprite will turn
  54. -- * myTicksLeft:  the number of ticks left to turn
  55. -- * myPauseTicks: the number of frames left to turn when the sprite is paused
  56. -- * myStopTicks:  value that the ticks will have when the rotation ends
  57. -- * myTimeUnit:   #ticks, #seconds, #minutes or #hours
  58. --
  59. -- The main handler is Turn me, activated on each prepareFrame.  I first
  60. -- determine how many ticks are left to run (myTicksLeft), then calculate what
  61. -- angle the sprite will turn in this time.  I obtain the current angle of the
  62. -- sprite by subtracting this angle from myFinalAngle.
  63. --
  64. -- The prepareFrame handler only calls Turn if myTicksLeft is not zero.
  65. -- I block myTicksLeft at zero when the time is up, with the command:
  66. --
  67. --   myTicksLeft = max (0, (myStopTicks - the ticks))
  68. --
  69. -- I use myTicksLeft both as a boolean (TRUE|FALSE) value and as an integer.
  70. -- Setting myTicksLeft to zero effectively stops the rotation.  If I first save
  71. -- the value of myTicksLeft in myPauseTicks, then I can restore this value
  72. -- later to make  the sprite resume its rotation from the point at which it was
  73. -- paused.
  74. --
  75. -- To reverse the direction of the sprite, I invert two values - myTotalAngle 
  76. -- and myAnglePerTick - and I set myTicksLeft so that it will reach zero when
  77. -- the sprite returns to its initial angle.
  78. --
  79. -- The TimedRotation_SetDuration call lets you change the value of
  80. -- myDuration even while the sprite is rotating.  To ensure that the sprite
  81. -- turns the correct total angle, I adjust myAnglePerTick  and set myTicksLeft
  82. -- in proportion to the angle the sprite has still to turn.
  83.  
  84. -- PUBLIC METHODS
  85. -- This behavior supports the following external calls.  See the handlers
  86. -- themselves for details and copy-and-paste examples.
  87. --
  88. -- * TimedRotation_SetInitialAngle me, theAngle
  89. -- * TimedRotation_SetTotalAngle me, theAngle
  90. -- * TimedRotation_SetDuration me, duration, timeUnit
  91. -- * TimedRotation_ToggleActive me, trueOrFalse
  92. -- * TimedRotation_TogglePause me, trueOrFalse
  93. -- * TimedRotation_ToggleDirection me, newDirection
  94. -- * TimedRotation_GetAngle me
  95. -- * TimedRotation_GetIncrement me
  96. -- * TimedRotation_GetReference
  97.  
  98.  
  99.  
  100. -- HISTORY --
  101.  
  102. -- 28 September 1998: written for the D7 Behaviors Palette by James Newton
  103. -- 23 November  1998: Public Methods descriptions added.  ErrorAlert modified.
  104.  
  105.  
  106.  
  107. -- PROPERTIES --
  108.  
  109. property mySprite
  110. -- error checking
  111. property getPDLError
  112. -- author-defined parameters
  113. property myInitialAngle
  114. property myTotalAngle
  115. property myDuration
  116. property myTimeUnit
  117. property myTicksLeft
  118. -- internal properties
  119. property myFinalAngle
  120. property myAnglePerTick
  121. property myStopTicks
  122. property myPauseTicks
  123.  
  124.  
  125.  
  126. -- EVENT HANDLERS --
  127.  
  128. on beginSprite me
  129.   Initialize me
  130.   
  131. end beginSprite
  132.  
  133.  
  134. on prepareFrame me
  135.   --  if myTicksLeft then Turn me
  136.   Turn me
  137. end prepareFrame
  138.  
  139.  
  140.  
  141. -- CUSTOM HANDLERS --
  142.  
  143. on Initialize me -- sent by beginSprite
  144.   mySprite = sprite(me.spriteNum)
  145.   
  146.   -- Error checking
  147.   theMember  = mySprite.member
  148.   memberType = theMember.type
  149.   if PermittedMemberTypes(me).getPos(memberType) then
  150.     if memberType = #text then 
  151.       if theMember.boxType = #scroll then
  152.         ErrorAlert (me, #scrollingText, theMember)
  153.         theMember.boxType = #fixed
  154.       end if
  155.     end if
  156.   else
  157.     ErrorAlert (me, #invalidMemberType, memberType)
  158.   end if
  159.   -- End of error checking
  160.   
  161.   myDuration = ConvertToTicks (me, myDuration, myTimeUnit)
  162.   
  163.   if myTicksLeft then
  164.     SetAnglePerTick me
  165.     StartRotation me
  166.   end if
  167. end Initialize
  168.  
  169.  
  170. on ConvertToTicks me, duration, timeUnit
  171.   -- sent by Initialize, _SetDuration
  172.   -- Converts the chosen duration to a platform-dependent number of ticks
  173.   case timeUnit of
  174.     void, #ticks: -- nothing
  175.     #seconds: duration = duration * 60
  176.     #minutes: duration = duration * 60 * 60
  177.     #hours:   duration = duration * 60 * 60 * 60
  178.     otherwise
  179.       return #invalidSymbolError
  180.   end case
  181.   return integer (duration)
  182. end ConvertToTicks
  183.  
  184.  
  185. on SetAnglePerTick me
  186.   -- sent by Initialize, _SetFrameCount, _ToggleActive
  187.   myAnglePerTick = myTotalAngle / myDuration 
  188. end SetAnglePerTick
  189.  
  190.  
  191. on StartRotation me -- sent by Initialize, _ToggleActive
  192.   mySprite.rotation = myInitialAngle
  193.   myFinalAngle      = myInitialAngle + myTotalAngle
  194.   myTicksLeft       = myDuration
  195.   myStopTicks       = the ticks + myDuration
  196. end StartRotation
  197.  
  198.  
  199. on Turn me -- sent by prepareFrame
  200.   ticksLeft         = myStopTicks - the ticks
  201.   if myTicksLeft    = ticksLeft then exit
  202.   
  203.   myTicksLeft       = max (0, ticksLeft)
  204.   remainingAngle    = myAnglePerTick * myTicksLeft
  205.   newAngle          = myFinalAngle - remainingAngle
  206.   mySprite.rotation = newAngle 
  207. end Turn
  208.  
  209.  
  210.  
  211. -- PUBLIC METHODS (responses to #sendSprite, #sendAllSprites, #call) --
  212.  
  213. on TimedRotation_SetInitialAngle me, theAngle
  214.   -- Sets initial angle (takes effect from next _ToggleActive call)
  215.   -- Examples:
  216.   --
  217.   --  sendSprite (1, #TimedRotation_SetInitialAngle, 180.0)
  218.   --
  219.   --  sendAllSprites (#TimedRotation_SetInitialAngle, 90.0)
  220.   --
  221.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  222.   --  call (#TimedRotation_SetInitialAngle, rotationRef, 45.0)
  223.   
  224.   -- Error check
  225.   case ilk (theAngle) of
  226.     #float, #integer: -- nothing
  227.     otherwise
  228.       return #invalidTypeError
  229.   end case
  230.   -- End of error check
  231.   
  232.   myInitialAngle = theAngle
  233. end TimedRotation_SetInitialAngle
  234.  
  235.  
  236. on TimedRotation_SetTotalAngle me, theAngle
  237.   -- Sets angle to rotate (takes effect from next _ToggleActive call)
  238.   -- Examples:
  239.   --
  240.   --  sendSprite (1, #TimedRotation_SetTotalAngle, 180.0)
  241.   --
  242.   --  sendAllSprites (#TimedRotation_SetTotalAngle, 720.0)
  243.   --
  244.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  245.   --  call (#TimedRotation_SetTotalAngle, rotationRef, 45.0)
  246.   
  247.   case ilk (theAngle) of
  248.     #float:   myTotalAngle = theAngle
  249.     #integer: myTotalAngle = float (theAngle)
  250.     otherwise
  251.       -- Error check
  252.       return #invalidTypeError
  253.   end case
  254. end TimedRotation_SetTotalAngle
  255.  
  256.  
  257. on TimedRotation_SetDuration me, duration, timeUnit
  258.   -- Modifies the time that rotation is to last.
  259.   -- duration can be any positive number (integer|float)
  260.   -- timeUnit can be void|#ticks|#seconds|#minutes|#hours (void acts as #ticks)
  261.   -- Changes remaining time proportionately if sprite is currently rotating
  262.   -- Examples:
  263.   --
  264.   --  sendSprite (1, #TimedRotation_SetDuration, 18, #seconds)
  265.   --
  266.   --  sendAllSprites (#TimedRotation_SetDuration, 1.7, #minutes)
  267.   --
  268.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  269.   --  call (#TimedRotation_SetDuration, rotationRef, 45, #ticks)
  270.   
  271.   -- Error check
  272.   case ilk (duration) of
  273.     #integer, #float:
  274.       if duration < 1 then
  275.         return #outOfRangeError
  276.       end if
  277.     otherwise
  278.       return #invalidTypeError
  279.   end case
  280.   duration = ConvertToTicks (me, duration, timeUnit)
  281.   if ilk (duration) <> #integer then
  282.     return duration
  283.   end if
  284.   -- End of error check
  285.   
  286.   if myTicksLeft then
  287.     myTicksLeft = (myTicksLeft * duration) / myDuration
  288.     myStopTicks = the ticks + myTicksLeft
  289.   else if myPauseTicks then
  290.     myPauseTicks = (myPauseTicks * duration) / myDuration
  291.   end if
  292.   myDuration = duration
  293.   SetAnglePerTick me
  294. end TimedRotation_SetDuration
  295.  
  296.  
  297. on TimedRotation_ToggleActive me, trueOrFalse
  298.   -- Stops rotation or restarts it from myInitialAngle.
  299.   -- trueOrFalse is an optional parameter
  300.   -- Examples:
  301.   --
  302.   --  sendSprite (1, #TimedRotation_ToggleActive)
  303.   --
  304.   --  sendAllSprites (#TimedRotation_ToggleActive, TRUE)
  305.   --
  306.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  307.   --  call (#TimedRotation_ToggleActive, rotationRef, 0)
  308.   
  309.   if voidP (trueOrFalse) then
  310.     myTicksLeft = not myTicksLeft
  311.   else if ilk (trueOrFalse) <> #integer then
  312.     -- Error check
  313.     return #invalidTypeError
  314.   else
  315.     myTicksLeft = trueOrFalse <> 0
  316.   end if
  317.   
  318.   if myTicksLeft then
  319.     SetAnglePerTick me
  320.     StartRotation me
  321.   end if
  322. end TimedRotation_ToggleActive
  323.  
  324.  
  325. on TimedRotation_TogglePause me, trueOrFalse
  326.   -- Pauses or continues rotation from where it was paused
  327.   -- trueOrFalse is an optional parameter
  328.   -- Examples:
  329.   --
  330.   --  sendSprite (1, #TimedRotation_TogglePause)
  331.   --
  332.   --  sendAllSprites (#TimedRotation_TogglePause, TRUE)
  333.   --
  334.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  335.   --  call (#TimedRotation_TogglePause, rotationRef, 0)
  336.   
  337.   pauseTicks = myTicksLeft
  338.   if voidP (trueOrFalse) then
  339.     myTicksLeft = not myTicksLeft
  340.   else if ilk (trueOrFalse) <> #integer then
  341.     -- Error check
  342.     return #invalidTypeError
  343.   else
  344.     if (not myTicksLeft = not trueOrFalse) then
  345.       -- Don't change pause state
  346.       exit
  347.     end if
  348.     
  349.     myTicksLeft = trueOrFalse
  350.   end if
  351.   
  352.   if myTicksLeft then
  353.     myTicksLeft  = myPauseTicks
  354.     myStopticks  = the ticks + myTicksLeft
  355.     myPauseTicks = 0
  356.   else
  357.     myPauseTicks = pauseTicks
  358.   end if
  359. end TimedRotation_TogglePause
  360.  
  361.  
  362. on TimedRotation_ToggleDirection me, newDirection
  363.   -- Reverse/sets the direction of rotation.  The sprite will stop rotating
  364.   -- when it reaches myInitialAngle.  (If you use this command an even number
  365.   -- of times, the sprite will stop once it has turned through myTotalAngle).
  366.   -- newDirection is an optional parameter.  It can take the values
  367.   -- void|#clockwise|TRUE|#antiClockwise|#counterClockwise|FALSE
  368.   -- A void value for newDirection will reverse the direction of rotation
  369.   -- Examples:
  370.   --
  371.   --  sendSprite (1, #TimedRotation_ToggleDirection)
  372.   --
  373.   --  sendAllSprites (#TimedRotation_ToggleDirection, #clockwise)
  374.   --
  375.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  376.   --  call (#TimedRotation_ToggleDirection, rotationRef, 0)
  377.   
  378.   if voidP (newDirection) then
  379.     anglePerTick = -myAnglePerTick
  380.   else
  381.     case newDirection of
  382.       #clockwise, TRUE:
  383.         anglePerTick = abs (myAnglePerTick)
  384.       #antiClockwise, #counterClockwise, FALSE:
  385.         anglePerTick = -abs (myAnglePerTick)
  386.       otherwise
  387.         -- Error check
  388.         return #invalidTypeError
  389.     end case
  390.     if myAnglePerTick = anglePerTick then exit
  391.   end if
  392.   
  393.   -- Return to initial angle
  394.   myAnglePerTick = anglePerTick
  395.   if myPauseTicks then
  396.     myPauseTicks = myDuration - myPauseTicks     
  397.     myFinalAngle = mySprite.rotation + (myAnglePerTick * myPauseTicks)
  398.   else -- if myTicksLeft then
  399.     myTicksLeft  = myDuration - myTicksLeft
  400.     myStopTicks  = the ticks + myTicksLeft
  401.     myFinalAngle = mySprite.rotation + (myAnglePerTick * myTicksLeft)
  402.   end if
  403.   myTotalAngle = -myTotalAngle
  404. end TimedRotation_ToggleDirection
  405.  
  406.  
  407. on TimedRotation_GetAngle me
  408.   -- Returns the current angle of the sprite
  409.   -- Examples:
  410.   --
  411.   --  put sendSprite (1, #TimedRotation_GetAngle)
  412.   --
  413.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  414.   --  put call (#TimedRotation_GetAngle, rotationRef)
  415.   
  416.   return mySprite.rotation
  417. end TimedRotation_GetAngle
  418.  
  419.  
  420. on TimedRotation_GetIncrement me
  421.   -- Returns the angle the sprite turns on each frame
  422.   -- Examples:
  423.   --
  424.   --  put sendSprite (1, #TimedRotation_GetIncrement)
  425.   --
  426.   --  rotationRef = sendSprite (1, #TimedRotation_GetReference)
  427.   --  put call (#TimedRotation_GetIncrement, rotationRef)
  428.   
  429.   return myAnglePerTick
  430. end TimedRotation_GetIncrement
  431.  
  432.  
  433. on TimedRotation_GetReference me, theList
  434.   -- Returns a reference to the current behavior.  theList is an optional
  435.   -- parameter.  Use an empty list in a sendAllSprites call to return a
  436.   -- list of all "Rotation (time-based)" behaviors in the current frame.  Use
  437.   -- an empty linear list to obtain a list of behaviors, or an empty 
  438.   -- property list to return a list with sprite numbers as the
  439.   -- properties and behavior references as the values.  Examples :
  440.   --
  441.   --   put sendAllSprites (#TimedRotation_GetReference, [])
  442.   --   -- [<offspring "Rotation (time-based)" 2 2f1b594>]
  443.   --
  444.   --   put sendAllSprites (#TimedRotation_GetReference, [:])
  445.   --   -- [1: <offspring "Rotation (time-based)" 2 2f1b594>]
  446.   --
  447.   -- If you leave "theList" void then the handler will return a reference to
  448.   -- the behavior on the given sprite (using sendSprite) or the highest sprite
  449.   -- with the behavior (using sendAllSprites).  Examples:
  450.   -- 
  451.   --   put sendSprite (1, #TimedRotation_GetReference)
  452.   --   -- <offspring "Rotation (time-based)" 2 2f1b594>
  453.   --
  454.   --   put sendAllSprites (#TimedRotation_GetReference)
  455.   --   -- <offspring "Rotation (time-based)" 2 2f0dac0>
  456.   
  457.   case ilk (theList) of
  458.     #list: theList.append(me)
  459.     #propList: theList.addProp(me.spriteNum, me)
  460.     otherwise
  461.       return me
  462.   end case
  463.   return theList
  464. end TimedRotation_GetReference
  465.  
  466.  
  467.  
  468. -- ERROR CHECKING --
  469.  
  470. on ErrorAlert me, theError, data
  471.   -- sent by getPropertyDescriptionList, Initialize
  472.   
  473.   case theError of
  474.     #getPDLError:
  475.       alert "¼
  476. Error: This behavior works only with the following members types:   "&¼
  477. permittedMemberTypes(me)&RETURN&RETURN&"¼
  478. Hit OK and then delete this behavior from the sprite."&RETURN&"¼
  479. For more information on deleting Behaviors, see the Help system."
  480.       if the optionDown then
  481.         return ¼
  482.  [ ¼
  483.  #getPDLError: ¼
  484.  [ ¼
  485.   #comment: "ERROR:  Wrong member type.  Click 'Cancel'.", ¼
  486.   #format:  #string, ¼
  487.   #range:   [""], ¼
  488.   #default:  "" ¼
  489.  ] ¼
  490. ]
  491.       end if
  492.       
  493.     otherwise
  494.       -- Determine the behavior's name
  495.       behaviorName = string (me)
  496.       delete word 1 of behaviorName
  497.       delete the last word of behaviorName
  498.       delete the last word of behaviorName
  499.       -- Convert #data to useful value
  500.       case data.ilk of
  501.         #void: data = "<void>"
  502.         #symbol: data = "#"&data
  503.       end case
  504.       
  505.       case theError of
  506.         #invalidMemberType:
  507.           alert "¼
  508. BEHAVIOR ERROR: Frame "&the frame&", Sprite "&me.spriteNum&RETURN&RETURN&"¼
  509. Behavior "&behaviorName&" only functions with the following member types:"&¼
  510. RETURN&permittedMemberTypes()&RETURN&RETURN&"¼
  511. Current type = "&data
  512.           halt
  513.           
  514.         #scrollingText:
  515.           if the runMode = "Author" then
  516.             memberName = data.name
  517.             if memberName = "" then
  518.               memberName = string (data)
  519.               delete memberName.word [1]
  520.               delete the last char of memberName
  521.             else
  522.               memberName = QUOTE&memberName"E
  523.             end if     
  524.             alert "¼
  525. BEHAVIOR ERROR: Frame "&the frame&", Sprite "&me.spriteNum&RETURN&"¼
  526. Behavior "&behaviorName&RETURN&RETURN&"¼
  527. Scroll bars of Text members cannot be rotated.  The boxType of the member "&¼
  528. memberName&" has been set to #fixed."
  529.           end if
  530.           
  531.       end case
  532.   end case
  533. end ErrorAlert
  534.  
  535.  
  536.  
  537. -- AUTHOR-DEFINED PARAMETERS --
  538.  
  539. on getPropertyDescriptionList me
  540.   
  541.   if not the currentSpriteNum then exit
  542.   
  543.   -- Error check
  544.   theMember = sprite(the currentSpriteNum).member
  545.   memberType = theMember.type
  546.   permittedTypes = PermittedMemberTypes(me)
  547.   if not permittedTypes.getPos(memberType) then
  548.     return errorAlert (me, #getPDLError, permittedTypes)
  549.   end if
  550.   -- End of error check
  551.   
  552.   return ¼
  553. [ ¼
  554.  #myInitialAngle: ¼
  555.  [ ¼
  556.   #comment: "Initial angle:", ¼
  557.   #format:  #float, ¼
  558.   #default:  sprite(the currentSpriteNum).rotation ¼
  559.  ], ¼
  560.  #myTotalAngle: ¼
  561.  [ ¼
  562.   #comment: "Turn clockwise through how many degrees?", ¼
  563.   #format:  #float, ¼
  564.   #default:  360 ¼
  565.  ], ¼
  566.  #myDuration: ¼
  567.  [ ¼
  568.   #comment: "Time taken to turn:", ¼
  569.   #format:  #integer, ¼
  570.   #range:  [#min: 1, #max: 120], ¼
  571.   #default:  60¼
  572.  ], ¼
  573.  #myTimeUnit: ¼
  574.  [ ¼
  575.   #comment: "", ¼
  576.   #format:  #symbol, ¼
  577.   #range:  [#ticks, #seconds, #minutes, #hours], ¼
  578.   #default: #seconds ¼
  579.  ], ¼
  580.  #myTicksLeft: ¼
  581.  [ ¼
  582.   #comment: "Start rotating on beginSprite?", ¼
  583.   #format:  #boolean, ¼
  584.   #default:  TRUE¼
  585.  ] ¼
  586. ]
  587. end getPropertyDescriptionList
  588.  
  589.  
  590. on PermittedMemberTypes me
  591.   -- sent by: getBehaviorDescription, getPropertyDescriptionList
  592.   -- ErrorAlert
  593.   return [#bitmap, #flash, #text, #vectorShape]
  594. end PermittedMemberTypes